package com.flot.yazb.base.rxjava.fld;


import android.app.Activity;
import android.net.ParseException;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.flot.yazb.aop.stub.CodeStub;
import com.flot.yazb.aop.stub.RMResponse;
import com.flot.yazb.widget.utils.ToastUtil;
import com.google.gson.JsonParseException;
import org.json.JSONException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import retrofit2.HttpException;
import rx.Observer;
import rx.android.BuildConfig;

/**
 * 参考资料： https://my.oschina.net/mastere/blog/1524034
 * Created by fengdongfei on 2017/8/28.
 */

public abstract class BaseObserver<T extends RMResponse> implements Observer<T> {

    private  Activity context;
    private BaseImpl mBaseImpl;
    //  Activity 是否在执行onStop()时取消订阅
    private boolean isAddInStop = false;
    private boolean needProgress = false;

    public BaseObserver(BaseImpl mBaseImpl, boolean needProgress, Activity context) {
        this.needProgress = needProgress;
        this.mBaseImpl = mBaseImpl;
        this.context=context;
    }
//    @Override
    public void onSubscribe(@NonNull Disposable d) {
        if(needProgress) mBaseImpl.showProgress("加载中");
        if (isAddInStop) {    //  在onStop中取消订阅
            mBaseImpl.addRxStop(d);
        } else { //  在onDestroy中取消订阅
            mBaseImpl.addRxDestroy(d);
        }
    }

    @Override
    public void onCompleted() {
        if(needProgress) mBaseImpl.dismissProgress();
    }

    @Override
    public void onError(Throwable e) {
        if (BuildConfig.DEBUG) {
            StringBuilder sb = new StringBuilder();
            StackTraceElement[] stacks = e.getStackTrace();
            sb.append(e.getMessage());
            sb.append("\n");
            for (StackTraceElement stack : stacks) {
                sb.append(stack.getMethodName());
                sb.append("(");
                sb.append(stack.getClassName());
                sb.append(".java:");
                sb.append(stack.getLineNumber());
                sb.append(")");
                sb.append("\n");
            }
            Log.d("Retrofit", sb.toString());
        }
        mBaseImpl.dismissProgress();
        if (e instanceof HttpException) {                 //   HTTP错误
            onException(ExceptionReason.BAD_NETWORK);
        } else if (e instanceof ConnectException
                || e instanceof UnknownHostException) {   //   连接错误
            onException(ExceptionReason.CONNECT_ERROR);
        } else if (e instanceof InterruptedIOException) { //  连接超时
            onException(ExceptionReason.CONNECT_TIMEOUT);
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {         //  解析错误
            onException(ExceptionReason.PARSE_ERROR);
        } else {
            onException(ExceptionReason.UNKNOWN_ERROR);
        }
    }

    @Override
    public void onNext(@NonNull T tBaseResponce) {
        if (tBaseResponce.code().equals(CodeStub.B_OK)) {
            onSuccess(tBaseResponce);
        } else {
            onFail(tBaseResponce);
        }
    }

    /**
     * 请求成功
     *
     * @param response 服务器返回的数据
     */
    abstract public void onSuccess(T response);
    abstract  public void onRelogin();

    /**
     * 服务器返回数据，但响应码不为200
     *
     * @param response 服务器返回的数据
     */
    public void onFail(T response) {
        String message = response.message();
        if (TextUtils.isEmpty(message)) {
            ToastUtil.showToast(context,response.code()+"");
        } else {
            ToastUtil.showToast(context,message);
        }
    }


    /**
     * 请求异常
     *
     * @param reason
     */
    public void onException(ExceptionReason reason) {
        switch (reason) {
            case CONNECT_ERROR:
                ToastUtil.showToast(context,"连接失败");
                break;

            case CONNECT_TIMEOUT:
                ToastUtil.showToast(context,"连接超时");
                break;

            case BAD_NETWORK:
                ToastUtil.showToast(context,"网络异常");
                break;

            case PARSE_ERROR:
                ToastUtil.showToast(context,"解析异常");
                break;

            case UNKNOWN_ERROR:
                ToastUtil.showToast(context,"未知错误");
                break;
            default:
                ToastUtil.showToast(context,"未知错误");
                break;
        }
    }

    /**
     * 请求网络失败原因
     */
    public enum ExceptionReason {
        /**
         * 解析数据失败
         */
        PARSE_ERROR,
        /**
         * 网络问题
         */
        BAD_NETWORK,
        /**
         * 连接错误
         */
        CONNECT_ERROR,
        /**
         * 连接超时
         */
        CONNECT_TIMEOUT,
        /**
         * 未知错误
         */
        UNKNOWN_ERROR,
    }
}
